<?php

namespace app\model;

use cgas\CGas;
use think\facade\Cache;
use think\helper\Str;
use think\Model;
use think\model\relation\HasOne;

class Order extends Model
{
    public function createOrder(): array
    {
        $uid = request()->param("uid");
        $user = app(User::class)->findOrFail($uid);
        $param = request()->param();
        $autoOrder = Cache::get("user_order_{$uid}_{$param["attr_id"]}");
        if ($autoOrder) throw new \Exception("系统检测到有一笔相同订单处理中，请稍后再试", 7059);
        Cache::set("user_order_{$uid}_{$param["attr_id"]}", 1, 3);//一分钟内禁止重复提交数据
        if ($user->is_del == 0 || $user->state == 2) throw new \Exception("用户不存在", 7056);
        $product = app(Product::class)->with(['attr' => function ($query) use ($param) {
            $query->where("id", $param["attr_id"]);
        }])->findOrFail($param['product_id']);
        $this->startTrans();
        $attr = $product->attr->toArray();
        $attr = array_column($attr, null, 'id')[$param['attr_id']] ?? [];
        if (empty($attr) || $attr['state'] != 1) throw new \Exception("商品规格不存在", 7057);
        if ($product['type'] == 2) {
            $code = app(ProductCode::class)->where(['pid' => $product['id'], 'aid' => $attr['id'], 'state' => 1])->find();
            if (empty($code)) throw new \Exception("权益卡券库存不足", 7057);
        } else if ($attr['stock'] < 1) throw new \Exception("库存不足", 7057);
//        $user =  app(User::class)->where("id", $uid)->find();
        if ($user['balance'] < bcmul($attr['price'], 100)) throw new \Exception("余额不足", 7058);
        $order = [
            "order_sn" => date("ymdHis") . Str::random(6, 1),
            "product_id" => $param['product_id'],
            "attr_id" => $param['attr_id'],
            "uid" => $uid,
            "state" => 1,
            "is_del" => 1,
            "price" => bcmul($attr['price'], 100),
            "account" => $param['account'],
            "code" => $product['type'] == 2 ? $code->code . "|" . $code->pwd : ($product['type'] == 3 ? $attr['url'] : ''),
        ];
        $this->save($order);
        //扣减积分
        $user->dec("balance", bcmul($attr['price'], 100))->save();
        //生成扣减日志
        app(UserBalance::class)->save([
            "uid" => $uid,
            "number" => bcmul($attr['price'], 100),
            "type" => 2,
            "content" => "兑换商品" . $product['name'],
        ]);
        switch ($product['type']) {
            case 1:
                $code = explode("-", $attr['code']);
                switch ($code[0]) {
                    case "cgas":
                        $account = json_decode($param['account'], true);
                        $account = array_column($account, null, 'text')['mobile'];
                        $cga = app(CGas::class)->pay(end($code), $account['value'], $this->order_sn);
                        if ($cga['code'] == 0) {
                            $cga = $cga['data']['ticket_list'];
                            $this->save([
                                "code" => $cga[0]['ticket_num'],
                                "cont" => json_encode($cga, 320)
                            ]);
                        } else {
                            //更新
                            @file_get_contents("https://pandalife.store/index/queryCode");
                        }
                        break;
                }
                break;
            case 2:
                $code->save(['uid' => $param['uid'], 'order_id' => $this->id, 'state' => 2, 'draw_time' => time(), 'trem' => date('Y-m-d H:i:s', strtotime('+' . $param['trem'] . ' day'))]);
                break;
        }
        //扣减产品库存
        app(ProductAttr::class)->where(['id' => $attr['id']])->dec('stock', 1)->save();
        app(UserValidateBalance::class)->decUpdateBalance($uid, (int)bcmul($attr['price'], 100));
        $this->commit();
        return $this->toArray();
    }

    public function product(): HasOne
    {
        return $this->hasOne(Product::class, "id", "product_id");
    }

    public function attr(): HasOne
    {
        return $this->hasOne(ProductAttr::class, "id", "attr_id");
    }

    public function user(): HasOne
    {
        return $this->hasOne(User::class, "id", "uid");
    }

    public function getPage(): array
    {
        $param = request()->param();
        $page = $param['page'] ?? 1;
        $limit = $param['limit'] ?? 50;
        $data = $this->with(['user', 'attr', 'product'])->when(!empty($param['uid']), function ($query) use ($param) {
            $query->where('uid', $param['uid']);
        })->when(!empty($param['product_id']), function ($query) use ($param) {
            $query->where('product_id', $param['product_id']);
        })->when(!empty($param['state']), function ($query) use ($param) {
            $query->where('state', $param['state']);
        })->when(!empty($param['order_sn']), function ($query) use ($param) {
            $query->where('order_sn', $param['order_sn']);
        })->when(!empty($param['attr_id']), function ($query) use ($param) {
            $query->where('attr_id', $param['attr_id']);
        })->when(!empty($param['account']), function ($query) use ($param) {
            $query->whereLike('account', "%{$param['account']}%");
        })->when(!empty($param['mobile']), function ($query) use ($param) {
            $uid = app(User::class)->where('mobile', $param['mobile'])->value('id');
            $query->where('uid', $uid);
        })->when(!empty($param['create_time']), function ($query) use ($param) {
            $query->whereBetween('create_time', [$param['create_time'][0] . " 00:00:00", $param['create_time'][1] . " 23:59:59"]);
        })->when(!empty($param['used_time']), function ($query) use ($param) {
            $query->whereBetween('used_time', [$param['used_time'][0] . " 00:00:00", $param['used_time'][1] . " 23:59:59"]);
        })/*->orderRaw('field(state,1,2,3,0)')*/ ->order(['create_time' => 'desc'])->paginate(['list_rows' => $limit, 'page' => $page])->toArray();
//        $money = $this->when(!empty($param['uid']), function ($query) use ($param) {
//            $query->where('uid', $param['uid']);
//        })->when(!empty($param['product_id']), function ($query) use ($param) {
//            $query->where('product_id', $param['product_id']);
//        })->when(!empty($param['state']), function ($query) use ($param) {
//            $query->where('state', $param['state']);
//        })->when(!empty($param['order_sn']), function ($query) use ($param) {
//            $query->where('order_sn', $param['order_sn']);
//        })->when(!empty($param['attr_id']), function ($query) use ($param) {
//            $query->where('attr_id', $param['attr_id']);
//        })->when(!empty($param['account']), function ($query) use ($param) {
//            $query->whereLike('account', "%{$param['account']}%");
//        })->when(!empty($param['mobile']), function ($query) use ($param) {
//            $uid = app(User::class)->where('mobile', $param['mobile'])->value('id');
//            $query->where('uid', $uid);
//        })->when(!empty($param['create_time']), function ($query) use ($param) {
//            $query->whereBetween('create_time', [$param['create_time'][0] . " 00:00:00", $param['create_time'][1] . " 23:59:59"]);
//        })->when(!empty($param['used_time']), function ($query) use ($param) {
//            $query->whereBetween('used_time', [$param['used_time'][0] . " 00:00:00", $param['used_time'][1] . " 23:59:59"]);
//        })->sum("price");
        return ['lst' => array_map(function ($item) {
            $item['price'] = (float)bcdiv($item['price'], 100, 2);
            if (!empty($item['account'])) {
                $account = json_decode($item['account'], true);
                $item['account'] = array_column($account, 'value', 'text');
            }
            if (!empty($item['cont'])) {
                $item['cont'] = json_decode($item['cont'], true);
//                dd($item);
                $item['expired_time'] = date('Y-m-d', $item['cont'][0]['expired_time']);
            }
            return $item;
        }, $data['data']), 'total' => $data['total'], 'last_page' => $data['last_page']];
    }

    public function chat(): array
    {
        $param = request()->param();
        $money = $this->when(!empty($param['uid']), function ($query) use ($param) {
            $query->where('uid', $param['uid']);
        })->when(!empty($param['product_id']), function ($query) use ($param) {
            $query->where('product_id', $param['product_id']);
        })->when(!empty($param['state']), function ($query) use ($param) {
            $query->where('state', $param['state']);
        })->when(!empty($param['order_sn']), function ($query) use ($param) {
            $query->where('order_sn', $param['order_sn']);
        })->when(!empty($param['attr_id']), function ($query) use ($param) {
            $query->where('attr_id', $param['attr_id']);
        })->when(!empty($param['account']), function ($query) use ($param) {
            $query->whereLike('account', "%{$param['account']}%");
        })->when(!empty($param['mobile']), function ($query) use ($param) {
            $uid = app(User::class)->where('mobile', $param['mobile'])->value('id');
            $query->where('uid', $uid);
        })->when(!empty($param['create_time']), function ($query) use ($param) {
            $query->whereBetween('create_time', [$param['create_time'][0] . " 00:00:00", $param['create_time'][1] . " 23:59:59"]);
        })->when(!empty($param['used_time']), function ($query) use ($param) {
            $query->whereBetween('used_time', [$param['used_time'][0] . " 00:00:00", $param['used_time'][1] . " 23:59:59"]);
        })->group('state')->field('sum(price) price,count(*) total,state')->select();
        return array_map(function ($item) {
            $item['price'] = (float)bcdiv($item['price'], 100, 2);
            return $item;
        }, array_column($money->toArray(), null, 'state'));
    }

    public function download(): array
    {
        $data = $this->getPage();
        $result = array_map(function ($item) {
            return [
                $item['order_sn'],
                $item['product']['name'],
                $item['attr']['name'],
                $item['price'],
                $item['user']['username'],
                $item['account']['mobile'] ?? '',
                $item['state'] == 1 ? '未使用' : ($item['state'] == 2 ? '已使用' : '已过期'),
                $item['create_time'],
                $item['used_time'],
                $item['cancel_time'],
            ];
        }, $data['lst']);
        $totalPage = $data['last_page'];
        $header = ['订单号', '商品名称', '商品规格', '价格', '用户名', '领取账号', '订单状态', '兑换时间', '使用时间', '过期时间'];
        $title = ["兑换记录"];
        $file = "兑换记录";
        return compact("result", "header", "title", "totalPage", "file");
    }

    public function addOrder()
    {
        $param = request()->param();
        $data = $this->where("id", $param['id'])->where("state", 3)->find();
        if (empty($data)) throw new \Exception("订单不存在");
        $order = $data->toArray();
        unset($order['id'], $order['create_time'], $order['update_time']);
        $order['cancel_time'] = $order['used_time'] = $order['code'] = $order['cont'] = null;
        $code = app(ProductAttr::class)->where('id', $order['attr_id'])->where('state', 1)->where('stock', '>', 0)->find();
        if (empty($code)) throw new \Exception("商品不存在");
        $order['order_sn'] = date("ymdHis") . Str::random(6, 1);
        $_code = explode("-", $code['code']);
        $_code = end($_code);
        $account = json_decode($data['account'], true)[0];
        $data->state = 4;
        $data->save();
        $order['state'] = 1;
        $this->exists(false)->save($order);
        $code->dec("stock", 1)->save();
        if (env('line.run')) {
            $chinaGas = (new CGas());
            $create = $chinaGas->pay($_code, $account['value'], $order['order_sn']);
            if ($create['code'] == 0) {
                $cga = $create['data']['ticket_list'];
                $this->where(['order_sn' => $order['order_sn']])->save([
                    "code" => $cga[0]['ticket_num'],
                    "cont" => json_encode($cga, 320)
                ]);
            } else {
                //更新
                @file_get_contents("https://pandalife.store/index/queryCode");
            }
        }
        return $order;
    }
}
